/**
 * 语音服务
 * 提供TTS语音播放、音频控制和流式播放功能
 */

import { ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'
import request from '@/utils/request'

// 音频播放状态
export interface AudioState {
  isPlaying: boolean
  isPaused: boolean
  isLoading: boolean
  currentTime: number
  duration: number
  volume: number
  playbackRate: number
}

// TTS请求参数
export interface TTSRequest {
  text: string
  character_name: string
  novel_project: string
  role_type?: string
  gender?: string
  effects?: {
    volume?: number
    pitch?: number
    speed?: number
    echo?: boolean
    reverb?: boolean
    [key: string]: any
  }
}

// TTS响应
export interface TTSResponse {
  audio_url: string
  character_name: string
  text: string
  voice_config: {
    voice_name: string
    gender: string
    language: string
    rate: string
    volume: string
    pitch: string
  }
}

class VoiceService {
  private currentAudio: HTMLAudioElement | null = null
  private audioCache = new Map<string, string>()
  private isInitialized = false

  // 音频状态
  public audioState = reactive<AudioState>({
    isPlaying: false,
    isPaused: false,
    isLoading: false,
    currentTime: 0,
    duration: 0,
    volume: 0.8,
    playbackRate: 1.0
  })

  // 播放队列
  private playQueue: Array<{ url: string; text: string; character: string }> = []
  private currentIndex = 0

  constructor() {
    this.init()
  }

  /**
   * 初始化语音服务
   */
  private init() {
    if (this.isInitialized) return

    // 监听页面卸载事件，清理资源
    window.addEventListener('beforeunload', () => {
      this.cleanup()
    })

    this.isInitialized = true
  }

  /**
   * 文字转语音
   */
  async textToSpeech(params: TTSRequest): Promise<TTSResponse | null> {
    try {
      this.audioState.isLoading = true
      
      const response = await request.post<TTSResponse>('/api/v1/audio/tts', params)
      
      if (response && response.audio_url) {
        // 缓存音频URL
        const cacheKey = this.generateCacheKey(params.text, params.character_name)
        this.audioCache.set(cacheKey, response.audio_url)
        
        return response
      }
      
      throw new Error('语音生成失败')
      
    } catch (error) {
      console.error('TTS请求失败:', error)
      ElMessage.error('语音生成失败，请重试')
      return null
    } finally {
      this.audioState.isLoading = false
    }
  }

  /**
   * 播放音频
   */
  async playAudio(
    audioUrl: string, 
    options: {
      text?: string
      character?: string
      autoPlay?: boolean
      volume?: number
      playbackRate?: number
    } = {}
  ): Promise<boolean> {
    try {
      // 停止当前播放
      this.stop()

      // 创建新的音频对象
      this.currentAudio = new Audio(audioUrl)
      
      // 设置音频属性
      this.currentAudio.volume = options.volume ?? this.audioState.volume
      this.currentAudio.playbackRate = options.playbackRate ?? this.audioState.playbackRate
      
      // 绑定事件监听器
      this.setupAudioEvents()
      
      // 预加载音频
      this.audioState.isLoading = true
      this.currentAudio.load()
      
      // 如果启用自动播放
      if (options.autoPlay !== false) {
        await this.play()
      }
      
      return true
      
    } catch (error) {
      console.error('音频播放失败:', error)
      ElMessage.error('音频播放失败')
      return false
    }
  }

  /**
   * 播放/恢复播放
   */
  async play(): Promise<void> {
    if (!this.currentAudio) return

    try {
      await this.currentAudio.play()
      this.audioState.isPlaying = true
      this.audioState.isPaused = false
    } catch (error) {
      console.error('播放失败:', error)
      ElMessage.error('播放失败，请检查音频文件')
    }
  }

  /**
   * 暂停播放
   */
  pause(): void {
    if (!this.currentAudio || !this.audioState.isPlaying) return

    this.currentAudio.pause()
    this.audioState.isPlaying = false
    this.audioState.isPaused = true
  }

  /**
   * 停止播放
   */
  stop(): void {
    if (!this.currentAudio) return

    this.currentAudio.pause()
    this.currentAudio.currentTime = 0
    this.audioState.isPlaying = false
    this.audioState.isPaused = false
    this.audioState.currentTime = 0
  }

  /**
   * 设置音量
   */
  setVolume(volume: number): void {
    volume = Math.max(0, Math.min(1, volume))
    this.audioState.volume = volume
    
    if (this.currentAudio) {
      this.currentAudio.volume = volume
    }
  }

  /**
   * 设置播放速度
   */
  setPlaybackRate(rate: number): void {
    rate = Math.max(0.25, Math.min(4, rate))
    this.audioState.playbackRate = rate
    
    if (this.currentAudio) {
      this.currentAudio.playbackRate = rate
    }
  }

  /**
   * 跳转到指定时间
   */
  seekTo(time: number): void {
    if (!this.currentAudio) return
    
    time = Math.max(0, Math.min(this.audioState.duration, time))
    this.currentAudio.currentTime = time
    this.audioState.currentTime = time
  }

  /**
   * 快进/快退
   */
  skip(seconds: number): void {
    if (!this.currentAudio) return
    
    const newTime = this.audioState.currentTime + seconds
    this.seekTo(newTime)
  }

  /**
   * 添加到播放队列
   */
  addToQueue(audioUrl: string, text: string, character: string): void {
    this.playQueue.push({ url: audioUrl, text, character })
  }

  /**
   * 播放队列中的下一个
   */
  playNext(): void {
    if (this.currentIndex < this.playQueue.length - 1) {
      this.currentIndex++
      const nextItem = this.playQueue[this.currentIndex]
      this.playAudio(nextItem.url, {
        text: nextItem.text,
        character: nextItem.character
      })
    }
  }

  /**
   * 播放队列中的上一个
   */
  playPrevious(): void {
    if (this.currentIndex > 0) {
      this.currentIndex--
      const prevItem = this.playQueue[this.currentIndex]
      this.playAudio(prevItem.url, {
        text: prevItem.text,
        character: prevItem.character
      })
    }
  }

  /**
   * 清空播放队列
   */
  clearQueue(): void {
    this.playQueue = []
    this.currentIndex = 0
  }

  /**
   * 一键播放消息（TTS + 播放）
   */
  async playMessage(
    text: string,
    characterName: string,
    novelProject: string,
    options: {
      roleType?: string
      gender?: string
      effects?: any
      autoPlay?: boolean
    } = {}
  ): Promise<boolean> {
    try {
      // 检查缓存
      const cacheKey = this.generateCacheKey(text, characterName)
      let audioUrl = this.audioCache.get(cacheKey)
      
      if (!audioUrl) {
        // 生成语音
        const ttsResponse = await this.textToSpeech({
          text,
          character_name: characterName,
          novel_project: novelProject,
          role_type: options.roleType,
          gender: options.gender,
          effects: options.effects
        })
        
        if (!ttsResponse) {
          return false
        }
        
        audioUrl = ttsResponse.audio_url
      }
      
      // 播放音频
      return await this.playAudio(audioUrl, {
        text,
        character: characterName,
        autoPlay: options.autoPlay
      })
      
    } catch (error) {
      console.error('播放消息失败:', error)
      return false
    }
  }

  /**
   * 获取可用语音列表
   */
  async getAvailableVoices(): Promise<any> {
    try {
      return await request.get('/api/v1/audio/voices')
    } catch (error) {
      console.error('获取语音列表失败:', error)
      return null
    }
  }

  /**
   * 检查浏览器音频支持
   */
  checkAudioSupport(): {
    canPlayMP3: boolean
    canPlayWAV: boolean
    canPlayAAC: boolean
    canPlayOGG: boolean
  } {
    const audio = new Audio()
    
    return {
      canPlayMP3: audio.canPlayType('audio/mpeg') !== '',
      canPlayWAV: audio.canPlayType('audio/wav') !== '',
      canPlayAAC: audio.canPlayType('audio/aac') !== '',
      canPlayOGG: audio.canPlayType('audio/ogg') !== ''
    }
  }

  /**
   * 设置音频事件监听器
   */
  private setupAudioEvents(): void {
    if (!this.currentAudio) return

    // 加载完成
    this.currentAudio.addEventListener('loadeddata', () => {
      this.audioState.isLoading = false
      this.audioState.duration = this.currentAudio?.duration || 0
    })

    // 时间更新
    this.currentAudio.addEventListener('timeupdate', () => {
      this.audioState.currentTime = this.currentAudio?.currentTime || 0
    })

    // 播放结束
    this.currentAudio.addEventListener('ended', () => {
      this.audioState.isPlaying = false
      this.audioState.isPaused = false
      this.audioState.currentTime = 0
      
      // 自动播放队列中的下一个
      if (this.playQueue.length > 0) {
        setTimeout(() => this.playNext(), 500)
      }
    })

    // 错误处理
    this.currentAudio.addEventListener('error', (e) => {
      console.error('音频播放错误:', e)
      this.audioState.isLoading = false
      this.audioState.isPlaying = false
      ElMessage.error('音频播放出错')
    })

    // 暂停事件
    this.currentAudio.addEventListener('pause', () => {
      this.audioState.isPlaying = false
    })

    // 播放事件
    this.currentAudio.addEventListener('play', () => {
      this.audioState.isPlaying = true
      this.audioState.isPaused = false
    })
  }

  /**
   * 生成缓存键
   */
  private generateCacheKey(text: string, character: string): string {
    return `${character}_${text.substring(0, 50)}_${text.length}`
  }

  /**
   * 清理资源
   */
  cleanup(): void {
    if (this.currentAudio) {
      this.currentAudio.pause()
      this.currentAudio = null
    }
    this.audioCache.clear()
    this.clearQueue()
  }

  /**
   * 获取当前音频状态
   */
  getAudioState(): AudioState {
    return { ...this.audioState }
  }

  /**
   * 切换播放/暂停
   */
  toggle(): void {
    if (this.audioState.isPlaying) {
      this.pause()
    } else {
      this.play()
    }
  }
}

// 创建全局语音服务实例
export const voiceService = new VoiceService()

// 导出类型
export type { AudioState, TTSRequest, TTSResponse }

// 导出便捷方法
export const useVoice = () => {
  return {
    voiceService,
    audioState: voiceService.audioState,
    playMessage: voiceService.playMessage.bind(voiceService),
    play: voiceService.play.bind(voiceService),
    pause: voiceService.pause.bind(voiceService),
    stop: voiceService.stop.bind(voiceService),
    toggle: voiceService.toggle.bind(voiceService),
    setVolume: voiceService.setVolume.bind(voiceService),
    setPlaybackRate: voiceService.setPlaybackRate.bind(voiceService),
    seekTo: voiceService.seekTo.bind(voiceService),
    skip: voiceService.skip.bind(voiceService)
  }
} 